Registered S3 method overwritten by 'quantmod':
method from
as.zoo.data.frame zoo
library(gridExtra)
Adjuntando el paquete: 'gridExtra'
The following object is masked from 'package:dplyr':
combine
library(plotly)
Adjuntando el paquete: 'plotly'
The following object is masked from 'package:ggplot2':
last_plot
The following object is masked from 'package:stats':
filter
The following object is masked from 'package:graphics':
layout
Cargando paquete requerido: sp
Adjuntando el paquete: 'raster'
The following object is masked from 'package:skimr':
bind
The following object is masked from 'package:plotly':
select
The following object is masked from 'package:dplyr':
select
library(lubridate)library(sf)
Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE
Juntamos y guardamos en un solo dataset todos los registros diarios del clima
# directorio_datos = "C:\\Users\\disar\\OneDrive\\Escritorio\\facultad python\\programacion_2_pablo\\TP2\\smn-data"# # Nombres de columnas# nombres_columnas = c("FECHA", "HORA", "TEMP", "HUM", "PNM", "DD", "FF", "NOMBRE")# # Anchos de las columnas# anchos_columnas <- c(8, 6, 6, 6, 7, 6, 8, 53)# # Clases (tipos) de las columnas# # Forzar FECHA a tipo character, para evitar que lo convierta a numérico y el primer "0" se borre# clases_columnas <- c("character", "numeric", "numeric", "numeric", "numeric", "numeric", "character", "character")# # # Listar todos los archivos que siguen el patrón "datohorario*.txt"# archivos <- list.files(path = directorio_datos, pattern = "datohorario.*\\.txt", full.names = TRUE)# # # Crear un objeto de progreso# pb <- progress_bar$new(# format = "Procesando :current/:total [:bar] :percent en :elapsedfull (:tick_rate/s - ETA: :eta)",# total = length(archivos),# clear = FALSE,# width = 80# )# # # Función para leer cada archivo# leer_archivo <- function(archivo) {# pb$tick() # Avanza la barra de progreso# # datos <- read.fwf(archivo, # col.names = nombres_columnas,# widths = anchos_columnas, # colClasses = clases_columnas,# fileEncoding = "ISO-8859-1", # skip = 2, # saltear dos primeras líneas# strip.white = TRUE, # borrar espacios en campos char# dec = ".")# # # Borrar filas con FECHA vacía o NA# datos <- datos |> filter(FECHA != "" & !is.na(FECHA))# # # Convertir la columna FECHA a formato Date con el patrón ddmmYYYY# datos$FECHA <- as.Date(datos$FECHA, format = "%d%m%Y")# # # Convertir FF a numérico# datos$FF <- as.numeric(datos$FF)# # return(datos)# }# # # Leer y combinar todos los archivos en un solo dataframe# df <- do.call(bind_rows, lapply(archivos, leer_archivo))# # # En vez de guardar un archivo csv, usar formato RDS, más abajo# # Guardar el dataframe df en un archivo CSV# # write.csv(df, "C://clean_msn//datos_smn.csv", row.names = FALSE)# # # Guardar el dataframe en formato RDS con compresión# saveRDS(df, file = "C:\\Users\\disar\\OneDrive\\Escritorio\\facultad python\\programacion_2_pablo\\TP2\\datos_smn.rds")
### Cargamos el datasetdf_smn <-readRDS('datos_smn.rds')
Diccionario
Dataset
Desc
smn_estaciones.csv
con datos de las estaciones meteorológicas de Argentina
smn_precipitaciones-1991-2024
con datos de precipitaciones
datohorario20230102.txt
Los datos diarios
n FECHA, HORA [HOA], TEMP [ºC], HUM [%], PNM [hPa], DD [gr], FF [km/hr],
Indicaciones
Combinar los datos provistos en un único dataset que contenga todos los datos relevantes
- Importar los datos y limpiarlos usando técnicas aprendidas en clase (dplyr, tidyr).
- Realizar un análisis exploratorio completo, incluyendo estadísticas descriptivas y visualizaciones con ggplot2 o plotly. Realizar gráficos georeferenciados interactivos.
- Identificar y comunicar los hallazgos más importantes del dataset.
- Identificar y manejar valores faltantes y duplicados.
- Transformar variables según sea necesario (por ejemplo, convertir fechas a un formato adecuado, categorizar variables, etc.).
df_precip_estaciones =left_join(raw_smn_precipitaciones, raw_estaciones, by ='id_estacion')# Convertir la columna Fecha en df_combinado a tipo Datedf_precip_estaciones$fecha =as.Date(df_precip_estaciones$fecha, format ="%Y-%m-%d")# Unir el dataframe combinado con el tercer datasetdf_completo =inner_join(df_precip_estaciones, df_smn, by =c("nombre", "fecha"))# write.csv(df_completo, "C:\\Users\\disar\\OneDrive\\Escritorio\\facultad python\\programacion_2_pablo\\TP2\\df_completo.csv", row.names = FALSE)
Luego de unir los datasets de estaciones, precipitaciones y datos climáticos, contamos con una base consolidada que nos permitirá analizar cómodamente las variables meteorológicas y su relación con la ubicación y el tiempo. Este análisis exploratorio inicial nos ayudará a entender mejor los datos, identificar patrones y destacar posibles irregularidades, preparando el camino para un estudio más detallado del clima en distintas regiones de Argentina.
Breve analisis superficial de las columnas, buscando NAs o valores atipicos
head(df_completo)
id_estacion fecha precipitacion año mes dia nombre
1 87007 2019-10-22 0 2019 10 22 LA QUIACA OBSERVATORIO
2 87007 2019-10-22 0 2019 10 22 LA QUIACA OBSERVATORIO
3 87007 2019-10-22 0 2019 10 22 LA QUIACA OBSERVATORIO
4 87007 2019-10-22 0 2019 10 22 LA QUIACA OBSERVATORIO
5 87007 2019-10-22 0 2019 10 22 LA QUIACA OBSERVATORIO
6 87007 2019-10-22 0 2019 10 22 LA QUIACA OBSERVATORIO
provincia altura latitud longitud hora temperatura humedad
1 jujuy 3459 -22.1 -65.6 0 8.2 61
2 jujuy 3459 -22.1 -65.6 1 7.0 64
3 jujuy 3459 -22.1 -65.6 2 6.1 66
4 jujuy 3459 -22.1 -65.6 3 4.8 72
5 jujuy 3459 -22.1 -65.6 4 3.7 73
6 jujuy 3459 -22.1 -65.6 5 2.8 75
presion_atmosferica direccion_viento velocidad_viento
1 3112 360 9
2 3111 360 9
3 3108 360 9
4 3105 0 0
5 3101 0 0
6 3098 0 0
summary(df_completo)
id_estacion fecha precipitacion año
Min. :87007 Min. :2018-01-01 Min. : 0.000 Min. :2018
1st Qu.:87305 1st Qu.:2019-10-02 1st Qu.: 0.000 1st Qu.:2019
Median :87497 Median :2021-06-13 Median : 0.000 Median :2021
Mean :87483 Mean :2021-05-30 Mean : 1.987 Mean :2021
3rd Qu.:87648 3rd Qu.:2023-01-31 3rd Qu.: 0.000 3rd Qu.:2023
Max. :87938 Max. :2024-09-20 Max. :276.000 Max. :2024
NA's :10699
mes dia nombre provincia
Min. : 1.000 Min. : 1.00 Length:4596655 Length:4596655
1st Qu.: 3.000 1st Qu.: 8.00 Class :character Class :character
Median : 6.000 Median :16.00 Mode :character Mode :character
Mean : 6.364 Mean :15.69
3rd Qu.: 9.000 3rd Qu.:23.00
Max. :12.000 Max. :31.00
altura latitud longitud hora
Min. : 5.0 Min. :-54.83 Min. :-72.05 Min. : 0.00
1st Qu.: 46.0 1st Qu.:-37.23 1st Qu.:-66.35 1st Qu.: 7.00
Median : 130.0 Median :-33.72 Median :-63.77 Median :12.00
Mean : 316.8 Mean :-34.56 Mean :-63.22 Mean :12.08
3rd Qu.: 461.0 3rd Qu.:-30.23 3rd Qu.:-59.05 3rd Qu.:18.00
Max. :3459.0 Max. :-22.10 Max. :-53.67 Max. :23.00
temperatura humedad presion_atmosferica direccion_viento
Min. :-19.80 Min. : 0.00 Min. : 9.3 Min. : 0.0
1st Qu.: 10.80 1st Qu.: 46.00 1st Qu.:1009.3 1st Qu.: 70.0
Median : 17.10 Median : 65.00 Median :1014.4 Median :180.0
Mean : 16.91 Mean : 63.85 Mean :1067.7 Mean :176.4
3rd Qu.: 23.00 3rd Qu.: 83.00 3rd Qu.:1020.4 3rd Qu.:270.0
Max. : 45.60 Max. :100.00 Max. :8500.0 Max. :990.0
NA's :1223 NA's :3762 NA's :88110 NA's :1569
velocidad_viento
Min. : 0.00
1st Qu.: 6.00
Median : 11.00
Mean : 13.24
3rd Qu.: 19.00
Max. :133.00
NA's :1577
Muchas columnas, dificil de leer aunque sea informacion clara
NAs de cada columna
Columna Cantidad_NA
id_estacion id_estacion 0
fecha fecha 0
precipitacion precipitacion 10699
año año 0
mes mes 0
dia dia 0
nombre nombre 0
provincia provincia 0
altura altura 0
latitud latitud 0
longitud longitud 0
hora hora 0
temperatura temperatura 1223
humedad humedad 3762
presion_atmosferica presion_atmosferica 88110
direccion_viento direccion_viento 1569
velocidad_viento velocidad_viento 1577
Dado que el dataset tiene 4.5 millones de observaciones, los 88,110 valores nulos en la columna de presión atmosférica representan menos del 2% del total. Este porcentaje de datos faltantes es relativamente bajo en comparación con el volumen total, por lo que no debería afectar significativamente el análisis de esta variable. Sin embargo, es recomendable evaluar si los valores nulos están distribuidos aleatoriamente o concentrados en ciertos períodos o estaciones, lo cual podría influir en la interpretación.
Ahora chequeamos si esa columna tiene valores atipicos
detectar_valores_atipicos <-function(df, columna_presion ="presion_atmosferica", max_presion =1040, min_presion =950) {# Filtrar filas con valores atípicos valores_atipicos <- df %>%filter(!!sym(columna_presion) > max_presion |!!sym(columna_presion) < min_presion)# Contar valores atípicos cantidad_atipicos <-nrow(valores_atipicos)# Imprimir el número de valores atípicos y los límites de presiónprint(paste("Cantidad de valores atípicos:", cantidad_atipicos))print(paste("Valor máximo de presión registrado en Argentina:", max_presion))print(paste("Valor mínimo de presión registrado en Argentina:", min_presion))# Guardar los valores atípicos en un nuevo dataframereturn(valores_atipicos)}# Ejemplo de usovalores_atipicos_presion <-detectar_valores_atipicos(df_completo, "presion_atmosferica")
[1] "Cantidad de valores atípicos: 392146"
[1] "Valor máximo de presión registrado en Argentina: 1040"
[1] "Valor mínimo de presión registrado en Argentina: 950"
Guardar el dataset de valores atípicos en un archivo CSV (opcional)
Viendo el dataset de los datos erroneos de, en 2019, se identificaron valores atípicos en los datos de la estación La Quiaca Observatorio, lo que sugiere problemas específicos en la recolección de información en esa ubicación. La concentración de errores en un solo punto resalta la importancia de investigar la causa raíz, ya que estos datos erróneos pueden distorsionar análisis climáticos y conducir a conclusiones incorrectas.
Ya que son al rededor de 400.000 de datos erroneos sumando los NAs podemos concluir que por ahi no es adecuado trabajar con esta columna, no eliminaremos las filas ya que son un monton, pero tampoco la utilizaremos.
Matriz de correlacion
Chequeamos la relacion de algunas variables para chequear que todo tenga sentido y el analisis valga la pena
library(ggcorrplot)library(corrplot)#Seleccionar solo las variables especificadasdf_seleccion <- df_completo %>% dplyr::select(precipitacion, altura, hora, humedad, temperatura, velocidad_viento)#Calcular la matriz de correlaciónmatriz_correlacion <-cor(df_seleccion, use ="complete.obs")#Graficar la matriz de correlacióncorrplot(matriz_correlacion, method ="circle", type ="upper",col =colorRampPalette(c("blue", "white", "red"))(200), tl.col ="black", tl.srt =45,title ="Matriz de Correlación entre Variables Seleccionadas")
Todo parece estar en orden, pasamos a un analisis más especifico
Ahora si pasamos a un analisis un poco mas profundo
# Cargar el archivo GeoJSON de las provinciasargentina <-st_read("provincia.JSON")
Reading layer `provincia' from data source
`C:\Users\disar\OneDrive\Escritorio\facultad python\programacion_2_pablo\TP2\provincia.json'
using driver `GeoJSON'
Simple feature collection with 24 features and 8 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -74 ymin: -90 xmax: -25 ymax: -21.78086
Geodetic CRS: WGS 84
argentina <- argentina %>%mutate(provincia =stri_trans_general(nam, "Latin-ASCII"))argentina <- argentina %>%mutate(provincia =str_to_lower(provincia))
Numero de estaciones por provincia
estaciones_por_provincia <- df_completo %>%group_by(provincia) %>%summarise(num_estaciones =n_distinct(id_estacion))ggplot(estaciones_por_provincia, aes(x =reorder(provincia, -num_estaciones), y = num_estaciones)) +geom_bar(stat ="identity", fill ="steelblue") +coord_flip() +labs(title ="Número de Estaciones Meteorológicas por Provincia",x ="Provincia",y ="Número de Estaciones")
Podemos observar una gran cantidad de estaciones meteorologicas en la provincia de buenos aires.
estaciones <- df_completo %>%distinct(id_estacion, .keep_all =TRUE) %>% dplyr::select(id_estacion, nombre, provincia, latitud, longitud)mapa_ggplot <-ggplot() +geom_sf(data = argentina, fill ="lightgray", color ="black") +geom_point(data = estaciones, aes(x = longitud, y = latitud, color = provincia, text = nombre), size =3, alpha =0.7) +labs(title ="Mapa de Estaciones Meteorológicas Únicas en Argentina",x ="Longitud",y ="Latitud" ) +scale_color_viridis_d(name ="Provincia") +theme_minimal()mapa_interactivo <-ggplotly(mapa_ggplot, tooltip ="text") mapa_interactivo